package com.bthdung.studios.lesson12.glUtil;

import com.bthdung.studios.lesson12.framework.Vector2;
import com.bthdung.studios.lesson12.framework.Vector3;
import com.bthdung.studios.lesson12.framework.VertexPositionTextureNormal;

import android.graphics.Bitmap;
import android.graphics.Color;


/*
 * Creates the terrain data using VertexPositionTextureNormal class
 * Good: Easy to manipulate, since dealing with a vertex as an independent object, not an array of values.
 * Bad : More memory and time is needed to construct and destroy objects.
*/

public final class Lab
{
	// Creates the terrain grid, normals are calculated later when the grid is
	// ready
	public static VertexPositionTextureNormal[] genGridVerts(int width, int height, float scale, Bitmap map)
	{
		int vertsCount = width * height;

		VertexPositionTextureNormal[] verts = new VertexPositionTextureNormal[vertsCount];

		int index = 0;

		for (int z = 0; z < height; z++)
		{
			for (int x = 0; x < width; x++)
			{
				Vector3 pos = new Vector3();
				pos.x = scale * (x - (width - 1) / 2f);
				pos.y = scale * (float) Color.red(map.getPixel(x, z)) / 7f;
				pos.z = scale * (z - (height - 1) / 2f);

				Vector3 normal = new Vector3(0, 0, 0);
				Vector2 textureCoordinate = new Vector2((float) x / (float) (width - 1), (float) z / (float) (height - 1));

				pos.y = scale * (float) Color.red(map.getPixel(x, z)) / 10f;

				verts[index] = new VertexPositionTextureNormal(pos, normal, textureCoordinate);

				index++;
			}
		}

		return verts;
	}

	public static void calcVertsNormals(short[] indices, VertexPositionTextureNormal[] verts)
	{
		for (int i = 0; i < indices.length; i += 3)
		{
			Vector3 v1 = verts[indices[i]].Position;
			Vector3 v2 = verts[indices[i + 1]].Position;
			Vector3 v3 = verts[indices[i + 2]].Position;

			Vector3 vu = Vector3.sub(v3, v1);
			Vector3 vt = Vector3.sub(v2, v1);

			Vector3 normal = Vector3.cross(vt, vu);
			normal.normalize();

			verts[indices[i]].Normal.add(normal);
			verts[indices[i + 1]].Normal.add(normal);
			verts[indices[i + 2]].Normal.add(normal);
		}

		for (int i = 0; i < verts.length; i++)
			verts[i].Normal.normalize();
	}

	// Generates the indices of a bruteforce GL_TRIANGLES terrain
	public static short[] getIndexes(int width, int height)
	{
		short[] indices = new short[3 * 2 * (width - 1) * (height - 1)];
		int vertIndex = 0;

		for (int i = 0; i <= height - 2; i++)
		{
			for (int j = 0; j <= width - 2; j++)
			{
				int t = j + i * width;

				indices[vertIndex++] = (short) (t + width + 1); // Bottom Right
				indices[vertIndex++] = (short) (t + 1); // Upper Right
				indices[vertIndex++] = (short) t; // Upper Left

				indices[vertIndex++] = (short) (t + width); // Bottom Left
				indices[vertIndex++] = (short) (t + width + 1); // Bottom Right
				indices[vertIndex++] = (short) t; // Upper left
			}
		}

		return indices;
	}
}
